import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Esta clase representa a un colocador de barcos. <p>
 * Esta clase apunta a Espacios y ademas funciona con la ayuda de CreaFlota para agregar barcos a los tableros.
 * @author Miguel Martinez Aguilar
 * @version 04 de abril de 2013
 */
public class Colocador extends Apuntador
{
    // Declaracion de variables de instancia
    private Barco elBarco;// es un barco.
    private Espacio[][] matriz;// es una matriz de Espacios de 10x10.
    private Espacio esp;// es un espacio.
    private CreaFlota creador;// es un objeto CreaFlota.
    private int longitud;// es la longitud del barco en turno.
    private Espacio[] arr;// es un arreglo de espacios.
    private boolean activado;// es un boleano que indica si este objeto esta activo.
    private boolean aleatorio;// es un boleano que indica si los barcos se agregan aleatoriamente o manual.
    private int cont;// es un contador de ciclos.

    /**
     * Este es el constructor de Colocador.
     * @param tab: una matriz de Espacios.
     * @param creador: el objeto CreaFlota al que se hara referencia.
     */
    public Colocador(Espacio[][] tab, CreaFlota creador)
    {
        super();
        elBarco = null;
        esp = (Espacio)tab[0][0];
        matriz = tab;
        this.creador = creador;
        longitud = 0;
        activado = false;
        aleatorio = false;
        cont = 0;
    }
    
    /**
     * Este metodo ubica a este objeto apuntador con el cursor.
     */
    public void act() 
    {
        if(elBarco != null){
            if(aleatorio){
                if(cont == 1)this.espacioAleatorio();
                if(cont > 25){
                    this.clickAleatorio();
                    cont = 0;
                }
                cont++;
            }
            else{
                this.clickAqui();
                if(activado){
                    super.cambiaCoordenadas();
                    if(activo)this.ubicaEspacio();
                }
            }
        }
    }
    
    /**
     * Este metodo selecciona un espacio al azar para evaluar su posicion.
     */
    public void espacioAleatorio()
    {
        creador.giraBarco(Greenfoot.getRandomNumber(2) > 0);
        alguien = this.tiroAleatorio();
        if(esp != (Espacio)alguien)esp.resalta(false);
        esp=(Espacio)alguien;
        this.ubicaBarco();
        if(this.sonValidos())creador.activaAncla(true);
        else creador.activaAncla(false);
    }
    
    /**
     * Este metodo busca un espacio aleatorio y lo regresa.
     */
    public Espacio tiroAleatorio()
    {
        int fila = Greenfoot.getRandomNumber(10);
        int col = Greenfoot.getRandomNumber(10);
        return (Espacio)matriz[fila][col];
    }
    
    /**
     * Este metodo simula un clic del mouse, con el objetivo de agregar barcos.
     */
    public void clickAleatorio()
    {
        if(this.sonValidos())creador.anclaBarco();
    }
    
    /**
     * Este es el metodo que verifica si se ha realizado un click con el mouse.
     */
    public void clickAqui()
    {
        if(super.clickValido()){
            elBarco.resalta(true);
            if(activado){
                activado = false;
                if(this.sonValidos())creador.activaAncla(true);
                else{
                    creador.activaAncla(false);
                    elBarco.resaltaRojo();
                }
            }
            else{
                activado = true;
                creador.activaAncla(false);
            }
        }
        else{
            if(activo){
                if(this.sonValidos())elBarco.resalta(true);
                else elBarco.resaltaRojo();
            }
        }
    }
    
    /**
     * Este es el metodo que checa si el puntero se encuentra con un espacio.
     */
    public void ubicaEspacio()
    {
        if(super.ubicaObjeto(false)){
            esp=(Espacio)alguien;
            this.ubicaBarco();
        }
    }
    
    /**
     * Este es el metodo que ubica al barco en el lugar actual del movedor.
     */
    public void ubicaBarco()
    {
        Espacio[] aux = new Espacio[longitud];
        int fila = esp.fila();
        int col = esp.col();
        if(elBarco.vertical()){
            if((fila + (longitud - 1)) > 9)fila = (9 - (longitud - 1));
            for(int i = 0; i < longitud; i++)arr[i] = (Espacio)matriz[fila + i][col];
        }
        else{
            if((col + (longitud - 1)) > 9)col = (9 - (longitud - 1));
            for(int i = 0; i < longitud; i++)arr[i] = (Espacio)matriz[fila][col + i];
        }
        elBarco.desAsignaEspacios();
        elBarco.asignaEspacios(arr,this.sonValidos());
    }
    
    /**
     * Este metodo regresa el estado del apuntador.
     * @param unBarco: un barco que el actor CreFlota le manda a Colocador.
     */
    public void tomaBarco(Barco unBarco)
    {
        longitud = unBarco.longitud();
        elBarco = unBarco;
        arr = new Espacio[longitud];
        if(!elBarco.vertical())for(int i = 0; i < longitud; i++)arr[i] = (Espacio)matriz[0][i];
        else for(int i = 0; i < longitud; i++)arr[i] = (Espacio)matriz[i][0];
        elBarco.asignaEspacios(arr,this.sonValidos());
    }  
    
    /**
     * Este metodo activa este objeto.
     */
    public void activar() 
    {
        activado = true;
    }
    
    /**
     * Este metodo deduce si los barcos se agregan aleatoriamente o a mano.
     * @param val: un boleano que indica si los barcos se agregan aleatoriamente o a mano.
     */
    public void esAleatorio(boolean val) 
    {
        aleatorio = val;
    }
    
    /**
     * Este metodo verifica si las posiciones de un barco son adecuados. <p>
     * Regresa un bolean verdadero si las posiciones son validas.
     */
    public boolean sonValidos()
    {
        int fila = 0;
        int col = 0;
        boolean val = true;
        for(int i = 0; i < longitud; i++){
            if(arr[i] != null){
                fila = arr[i].fila();
                col = arr[i].col();
                for(int f = (fila - 1); f <= (fila + 1); f++){
                    for(int c = (col - 1); c <= (col + 1); c++){
                        if(f > -1 && f < 10 && c > -1 && c < 10){
                            if(((Espacio)matriz[f][c]).hayBarco() != null)val = false;
                        }
                        if(!val)break;
                    }
                    if(!val)break;
                }
            }
            if(!val)break;
        }
        return val;
    }
    
    /**
     * Este metodo elimina este objeto
     */
    public void seElimina() 
    {
        World mundo = super.getWorld();
        mundo.removeObject(this);// con este metodo eliminamos un objeto del mundo
    }
}
